﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Hammock;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Hammock.Web;
namespace BoxNet
{
    public class Api
    {
        public Api(string key)
        {
            Key = key;
        }
        public string Key { get; set; }
        public string Ticket { get; set; }
        protected const string APIBASEURL = @"https://www.box.net";
        protected const string BASEPATH = @"/api/1.0/rest";

        public void GetLoginUri(string monitorURI, Action<string, Exception> callback)
        {
            // https://www.box.net/api/1.0/rest?action=get_ticket&api_key=
            DoNoCredentialsAsyncRetrieve(APIBASEURL, BASEPATH, (new[] { "action=get_ticket", "api_key=" + Key }).ToList(), "GET", (result) =>
            {
                if (result.Error != null)
                {
                    callback("", result.Error);
                    return;
                }
                else
                {
                    // Extract string from XML
                    var data = new Dictionary<string, string>();
                    (from node in result.XmlDoc.Elements("response")
                     select new KeyValuePair<string, string>(node.Name.LocalName, node.Value)).ToList().ForEach(item => data.Add(item.Key, item.Value));

                    if (data.ContainsKey("status") && data["status"] == "get_ticket_ok" && data.ContainsKey("ticket"))
                    {
                        callback(string.Format(@"https://www.box.net/api/1.0/auth/{0}&redirect={1}",data["ticket"],monitorURI),null );
                        return;
                    }
                    callback("", null);
                }
            }); 
        }

        private void applyParams(RestRequest request, List<string> parameters)
        {
            //request.AddParameter("oauth_callback", "oob");
            foreach (var parm in parameters)
            {
                var keyValue = parm.Split('=');
                if (keyValue.Length == 2)
                {
                    request.AddParameter(keyValue[0], keyValue[1]);
                }
            }
        }
        public class BoxNetException:Exception{
            public BoxNetException()
            {
                
            }
            public BoxNetException(string message)
                : base(message)
            {
                
            }
            public BoxNetException(string message, Exception innerException)
                : base(message, innerException)
            {
                
            }
        
        }

        public class ResponseResult
        {
            public ResponseResult() { }
            public ResponseResult(XDocument doc, string content, HttpStatusCode status, Exception error)
            {
                XmlDoc = doc;
                Content = content;
                Status = status;
            }

            public XDocument XmlDoc {
                get;set;
            }
            public Exception Error{
                get;set;
            }
            public HttpStatusCode Status {
                get;set;
            }
            public string Content
            {
                get;
                set;
            }
        }

        protected void ResponseCallback(RestRequest request, RestResponse response, object state, Action<ResponseResult> callback)
        {
            XDocument result = null;
            var content = "";
            BoxNetException exception = null;
            var httpStatusCode = HttpStatusCode.NoContent;
            try
            {
                if (response.InnerException != null)
                {
                    exception = new BoxNetException("Error retrieving response", response.InnerException);
                }
                else
                {
                    //var request = (HttpWebRequest)asyncResult.AsyncState;
                    //var response = (HttpWebResponse)request.EndGetResponse(asyncResult);
                    httpStatusCode = response.StatusCode;
                    result = XDocument.Parse(response.Content, LoadOptions.None);
                    content = response.Content;
                }
            }
            catch (BoxNetException ex1)
            {
                // Rest API Errors
                exception = ex1;
            }
            catch (WebException ex)
            {
                    exception = new BoxNetException("Error retrieving response", ex);
            }
            finally
            {
                // Check to make sure there hasn't been an exception.
                // If there has, we want to pass null to the callback.
                XDocument data = null;
                if (exception == null)
                    data = result;
                callback(new ResponseResult(data, content, httpStatusCode, exception));
            }
        }

        protected void DoNoCredentialsAsyncRetrieve(string baseUrl, string path, List<string> parameters, string httpMethod, Action<ResponseResult> callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");

            var client = new RestClient
            {
                Authority = baseUrl,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) },
            };

            var request = new RestRequest
            {
                Path = path,
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
            };
            applyParams(request, parameters);

            //ApplyDBOXOAuthToRequest(baseUrl, parameters, httpMethod, request);
            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallback(req, resp, state, callback);
            });
        }

        private string GetCredentials()
        {
            return null;
        }
        protected void DoAsyncRetrieve(string baseUrl, string path, List<string> parameters, string httpMethod, Action<ResponseResult> callback)
        {
            baseUrl = baseUrl.Replace("+", "%20");
            path = path.Replace(@"\", @"/").Replace("+", "%20");
            var credentials = GetCredentials();

            var client = new RestClient
            {
                Authority = baseUrl,
                Credentials = credentials,
                CacheOptions = new Hammock.Caching.CacheOptions { Mode = Hammock.Caching.CacheMode.AbsoluteExpiration, Duration = new TimeSpan(0, 0, 10) },
            };

            var request = new RestRequest
            {
                Path = path,
                Method = (httpMethod.Equals("post", StringComparison.InvariantCultureIgnoreCase) ? WebMethod.Post : WebMethod.Get),
            };
            applyParams(request, parameters);

            //ApplyDBOXOAuthToRequest(baseUrl, parameters, httpMethod, request);
            client.BeginRequest(request, (req, resp, state) =>
            {
                ResponseCallback(req, resp, state, callback);
            });
        }
    }
}
